package com.fc.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.fc.dto.CodeGenarateDTO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Configuration
public class AutoGenerateCodeUtil {

    @Resource
    private AutoCodeConfiguration codeConfiguration;

    public void autoGenerateCode(CodeGenarateDTO codeGenarateDTO){
        // 1、全局配置
        GlobalConfig globalConfig = new GlobalConfig();//构建全局配置对象
        String projectPath = System.getProperty("user.dir");// 获取当前用户的目录
        globalConfig
                .setOutputDir(projectPath + "/src/main/java")// 输出文件路径
                .setAuthor(codeGenarateDTO.getAuthor())// 设置作者名字
                .setOpen(false)// 是否打开资源管理器
                .setFileOverride(false)// 是否覆盖原来生成的
                .setIdType(IdType.ASSIGN_ID)// 主键策略
                .setDateType(DateType.ONLY_DATE)
//                .setSwagger2(true)
                .setSwagger2(true)//自动开启swagger2的支持
                .setBaseResultMap(true)// 生成resultMap
                //设置不生成基础列
                .setBaseColumnList(false)// XML中生成基础列
                .setServiceName("%sService");// 生成的service接口名字首字母是否为I，这样设置就没有I

        // 2、数据源配置
        DataSourceConfig dataSourceConfig = new DataSourceConfig();// 创建数据源配置
        dataSourceConfig
                .setUrl(codeConfiguration.getUrl())
                .setDriverName(codeConfiguration.getDriver())
                .setUsername(codeConfiguration.getUsername())
                .setPassword(codeConfiguration.getPassword());
        if("mysql".equals(codeGenarateDTO.getDbType())) {
                dataSourceConfig.setDbType(DbType.MYSQL);
        }else if("oracle".equals(codeGenarateDTO.getDbType())){
            dataSourceConfig.setDbType(DbType.ORACLE);
        }

        // 3、包配置
        PackageConfig packageConfig = new PackageConfig();
        packageConfig
                .setModuleName(codeGenarateDTO.getModuleName())
                .setParent(codeGenarateDTO.getParent())
                .setEntity("entity")
                .setController("controller")
                .setService("service")
                .setMapper("mapper");

        // 4、策略配置
        StrategyConfig strategyConfig = new StrategyConfig();
        if("oracle".equals(codeGenarateDTO.getDbType())){
            strategyConfig.setInclude(codeGenarateDTO.getInclude().toUpperCase());// 设置要映射的表
        }else{
            strategyConfig.setInclude(codeGenarateDTO.getInclude());// 设置要映射的表
        }
        strategyConfig
                .setCapitalMode(true)// 开启全局大写命名
                .setNaming(NamingStrategy.underline_to_camel)// 下划线到驼峰的命名方式
                .setColumnNaming(NamingStrategy.underline_to_camel)// 下划线到驼峰的命名方式
                .setEntityLombokModel(codeGenarateDTO.getLombokFlag())// 是否使用lombok
                .setRestControllerStyle(codeGenarateDTO.getRestFlag())// 是否开启rest风格
                .setControllerMappingHyphenStyle(false);// controller层，开启下划线url
        if(StringUtils.isNotBlank(codeGenarateDTO.getLogicDeleteFieldName())){
            strategyConfig.setLogicDeleteFieldName(codeGenarateDTO.getLogicDeleteFieldName());
        }



        // 5、自定义配置（配置输出xml文件到resources下，生成thymeleaf的list页面）
        // 结合自定义模版来使用
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                //在模版引擎中使用时，通过 cfg.key 的形式调用
                Map<String,Object> map = new HashMap<String, Object>();
                map.put("query",codeGenarateDTO.getQuery());
                map.put("list",codeGenarateDTO.getList());
                map.put("form",codeGenarateDTO.getForm());
                this.setMap(map);
            }
        };
        List<FileOutConfig> focList = new ArrayList<FileOutConfig>();

        //输出html文件到resouces下
        String listHtmlPath = "/templates/list.html.vm";
        focList.add(new FileOutConfig(listHtmlPath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名
                return projectPath + "/src/main/resources/templates/"+
                        lowerFirst(tableInfo.getEntityName())+"/"
                        + "list.html" ;
            }
        });
        String formHtmlPath = "/templates/form.html.vm";
        focList.add(new FileOutConfig(formHtmlPath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名
                return projectPath + "/src/main/resources/templates/"+
                        lowerFirst(tableInfo.getEntityName())+"/"
                        +"form.html" ;
            }
        });
        cfg.setFileOutConfigList(focList);


        // 6、整合配置
        AutoGenerator autoGenerator = new AutoGenerator();// 构建代码生自动成器对象
        autoGenerator
                .setGlobalConfig(globalConfig)// 将全局配置放到代码生成器对象中
                .setDataSource(dataSourceConfig)// 将数据源配置放到代码生成器对象中
                .setPackageInfo(packageConfig)// 将包配置放到代码生成器对象中
                .setStrategy(strategyConfig)// 将策略配置放到代码生成器对象中
                .setCfg(cfg)// 将自定义配置放到代码生成器对象中
                .execute();// 执行！
    }

    /**
     * 将字符串的首字母转小写
     * @param str 需要转换的字符串
     * @return
     */
    private static String lowerFirst(String str) {
        // 同理
        char[] cs=str.toCharArray();
        cs[0]+=32;
        return String.valueOf(cs);
    }

}
